/*
 * Lenovo Group
 * Copyright (c) 2015-2016 All Rights Reserved.
 * Project Name: lmrp-android framework
 * Create Time: 16-2-16 下午6:51
 */

package com.lenovo.framework.service;

import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.model.LatLng;
import com.lenovo.framework.util.DLog;

import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;

/**
 * more detail, visit <a href="$inet://http://lbsyun.baidu.com/"><font
 * color="#0000ff"><u>http://lbsyun.baidu.com/</u></font></a>
 * @author JeffreyHe
 * @version 1.0
 * @updated 26-一月-2016 15:56:07
 */
public class LocationService extends Service implements BDLocationListener {
    private LocationClient mLocationClient;
    private LocationBinder locationBinder;
    private static LocationSuccessListener obj = new LocationSuccessListener() {
        @Override
        public void onReceiveLocation(BDLocation location) {
        }
    };
    private static ConcurrentHashMap<Intent, LocationSuccessListener> listenerLinkedHashMap = new ConcurrentHashMap<>();
    //地点和时间信息存起来备用, 1 分钟之内LocationService返回相同位置, 容量10
    private static final int HISTORY_LOCATIONS = 10;
    private static ConcurrentHashMap<Long, BDLocation> locations = new ConcurrentHashMap<>();

    public LocationService() {
        //listenerLinkedHashMap.clear();
    }

    public static LatLng getRealTimeLatLngTimeless(){
        if(locations.size() > 0) {
            Long max = Collections.max(locations.keySet());
            BDLocation bdLocation = locations.get(max);
            DLog.i("onreceive local", bdLocation.getCity());
            return new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
        }
        return null;
    }

    public static LatLng getRealTimeLatLng(){
        if(locations.size() > 0) {
            Long max = Collections.max(locations.keySet());
            if (System.currentTimeMillis() - max < 10000) {
                BDLocation bdLocation = locations.get(max);
                DLog.i("onreceive local", bdLocation.getCity());
                return new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
            }
        }
        return null;
    }

    public boolean onUnbind(Intent intent){
        listenerLinkedHashMap.remove(intent);
        return  super.onUnbind(intent);
    }

    public static class LocationConnection implements ServiceConnection {
        private final Intent intent;
        private LocationSuccessListener listener;

        public LocationConnection(LocationSuccessListener listener, Intent intent){
            this.listener = listener;
            this.intent = intent;
            if(listener == null)
                listener = obj;
            listenerLinkedHashMap.put(intent, listener);
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            DLog.w("location:", name + "location service bind success");
            //用来访问service中的数据
            if(listener == null)
                listener = obj;
            listenerLinkedHashMap.put(intent, listener);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            listenerLinkedHashMap.remove(intent);
            DLog.w("location:", "location bind fail");
        }
    }

    public static ServiceConnection connection(final LocationSuccessListener listener, final Intent intent){
        return new LocationConnection(listener, intent);
    }

    @Override
    public IBinder onBind(Intent intent) {
        if(locations.size() > 0) {
            Long max = Collections.max(locations.keySet());
            if (System.currentTimeMillis() - max < 8000) {
                BDLocation bdLocation = locations.get(max);
                DLog.i("onreceive local", bdLocation.getCity());
                for (LocationSuccessListener listener : listenerLinkedHashMap.values()) {
                    DLog.w("loc:", listener.getClass().getName());
                    if (listener != obj) {
                        listener.onReceiveLocation(bdLocation);
                    }
                }
                listenerLinkedHashMap.remove(intent);
                return null;
            }
        }
        return locationBinder;
    }

    public class LocationBinder extends Binder {
        public LocationService getService() {
            return LocationService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        locationBinder = new LocationBinder();
        mLocationClient = new LocationClient(getApplicationContext());
        mLocationClient.registerLocationListener(this);
        initLocation();
    }


    private void initLocation() {

        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Battery_Saving
        );//可选，默认高精度，设置定位模式，高精度，低功耗，仅设备
        option.setCoorType("bd09ll");//可选，默认gcj02，设置返回的定位结果坐标系
        option.setScanSpan(0);//可选，默认0，即仅定位一次，设置发起定位请求的间隔需要大于等于1000ms才是有效的
        option.setIsNeedAddress(true);//可选，设置是否需要地址信息，默认不需要
        option.setTimeOut(5000);
        option.setOpenGps(true);//可选，默认false,设置是否使用gps
        option.setLocationNotify(false);//可选，默认false，设置是否当gps有效时按照1S1次频率输出GPS结果
        option.setIsNeedLocationDescribe(true);//可选，默认false，设置是否需要位置语义化结果，可以在BDLocation.getLocationDescribe里得到，结果类似于“在北京天安门附近”
        option.setIsNeedLocationPoiList(true);//可选，默认false，设置是否需要POI结果，可以在BDLocation.getPoiList里得到
        option.setIgnoreKillProcess(false);//可选，默认false，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认杀死
        option.SetIgnoreCacheException(true);//可选，默认false，设置是否收集CRASH信息，默认收集
        option.setEnableSimulateGps(false);//可选，默认false，设置是否需要过滤gps仿真结果，默认需要
        mLocationClient.setLocOption(option);
        mLocationClient.start();
    }

    @Override
    public void onReceiveLocation(BDLocation bdLocation) {
        for(LocationSuccessListener listener : listenerLinkedHashMap.values()){
            DLog.i("listeners", listener == null ? "null" : listener.getClass().getName());
        }
        if(locations.size() > HISTORY_LOCATIONS){
            Long min = Collections.min(locations.keySet());
            locations.remove(min);
        }
        locations.put(System.currentTimeMillis(), bdLocation);
        int loactionType = bdLocation.getLocType();
        if (bdLocation != null) {
            DLog.i("onreceive remote", bdLocation.getCity());
            for(Intent intent : listenerLinkedHashMap.keySet()){
                LocationSuccessListener listener = listenerLinkedHashMap.get(intent);
                if(listener != obj) {
                    DLog.w("loc:", listener.getClass().getName());
                    listener.onReceiveLocation(bdLocation);
                }else {
                    onUnbind(intent);
                }
            }
        } else {
            DLog.toast("定位失败，请重试...");
        }
    }

	/**
	 * location service using baidu location
	 * @author JeffreyHe
	 * @version 1.0
	 * @updated 26-一月-2016 15:56:07
	 */
    public interface LocationSuccessListener {
        void onReceiveLocation(BDLocation location);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(mLocationClient != null) {
            mLocationClient.stop();
            mLocationClient = null;
        }
        //locations.clear();
        listenerLinkedHashMap.clear();
    }
}
